#include <glib.h>

struct ffmpeg_wrap {
	char *input_url;
	char *output_url;
	GVariantDict *input_dict;
	GVariantDict *output_dict;
	gboolean overwrite;
};


struct ffmpeg_wrap *ffmpeg_wrap_new(void)
{
	struct ffmpeg_wrap *wrap;

	wrap = g_new0(struct ffmpeg_wrap, 1);
	wrap->input_dict = g_variant_dict_new(NULL);
	wrap->output_dict = g_variant_dict_new(NULL);
	wrap->overwrite = FALSE;

	return wrap;
}

void ffmpeg_wrap_free(struct ffmpeg_wrap *wrap)
{
	g_free(wrap->input_url);
	g_free(wrap->output_url);
	g_variant_dict_unref(wrap->input_dict);
	g_variant_dict_unref(wrap->output_dict);
	g_free(wrap);
}

void ffmpeg_wrap_input_set_url(struct ffmpeg_wrap *wrap, const gchar *url)
{
	if (wrap->input_url)
		g_free(wrap->input_url);
	wrap->input_url = g_strdup(url);
}

void ffmpeg_wrap_output_set_url(struct ffmpeg_wrap *wrap, const gchar *url)
{
	if (wrap->output_url)
		g_free(wrap->output_url);
	wrap->output_url = g_strdup(url);
}

/*
 * 设置输出视频分辨率，默认使用源视频分辨率
 * 如：1280, 720
 */
void ffmpeg_wrap_output_set_size(struct ffmpeg_wrap *wrap, guint width, guint height)
{
	g_variant_dict_insert(wrap->output_dict, "-s", "(uu)", width, height);
}

/*
 * 设置输出音频编码格式，不设置ffmpeg会根据输出文件名自动推导，设置为"copy"，
 * 可以直接复制音频，避免解码和编码，但如果输出文件容器不支持，执行会失败
 * 如："aac"
 */
void ffmpeg_wrap_output_set_acodec(struct ffmpeg_wrap *wrap, const gchar *acodec)
{
	g_variant_dict_insert(wrap->output_dict, "-acodec", "s", acodec);
}

/*
 * 设置输出音频编码器格式，不设置ffmpeg会根据输出文件名自动推导，设置为"copy",
 * 可以直接复制视频，避免解码和编码，但如果输出文件容器不支持，执行会失败
 * 如："h264"
 */
void ffmpeg_wrap_output_set_vcodec(struct ffmpeg_wrap *wrap, const gchar *vcodec)
{
	g_variant_dict_insert(wrap->output_dict, "-vcodec", "s", vcodec);
}

/*
 * 设置输出帧率，默认25
 */
void ffmpeg_wrap_output_set_fps(struct ffmpeg_wrap *wrap, guint fps)
{
	g_variant_dict_insert(wrap->output_dict, "-r", "u", fps);
}

/*
 * 设置最大输出码率，单位：kbps
 */
void ffmpeg_wrap_output_set_maxrate(struct ffmpeg_wrap *wrap, guint maxrate)
{
	g_variant_dict_insert(wrap->output_dict, "-maxrate", "u", maxrate);
}

/*
 * 设置最小输出码率，单位：kbps
 */
void ffmpeg_wrap_output_set_minrate(struct ffmpeg_wrap *wrap, guint minrate)
{
	g_variant_dict_insert(wrap->output_dict, "-minrate", "u", minrate);
}

/*
 * 不输出音频
 */
void ffmpeg_wrap_output_disable_audio(struct ffmpeg_wrap *wrap)
{
	g_variant_dict_insert(wrap->output_dict, "-an", "s", "");
}

/*
 * 不输出视频
 */
void ffmpeg_wrap_output_disable_video(struct ffmpeg_wrap *wrap)
{
	g_variant_dict_insert(wrap->output_dict, "-vn", "s", "");
}

/*
 * 如果输出文件名重复，覆盖
 */
void ffmpeg_wrap_output_set_overwrite(struct ffmpeg_wrap *wrap)
{
	wrap->overwrite = TRUE;
}

static GString *get_kwargs(GString *comand, GVariantDict *dict)
{
	GVariantIter iter;
	GVariant *value;
	gchar *key;

	g_variant_iter_init(&iter, g_variant_dict_end(dict));
	while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
		if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
			g_string_append_printf(comand, "%s %s ", key, g_variant_get_string(value, NULL));
		} else if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
			g_string_append_printf(comand, "%s %u ", key, g_variant_get_uint32(value));
		} else if (g_variant_is_of_type(value, G_VARIANT_TYPE_TUPLE)) {
			/* FIXME: 目前tuple只能分辨率，但也许这样做并不安全 */
			guint32 width, height;
			g_variant_get(value, "(uu)", &width, &height);
			g_string_append_printf(comand, "%s %ux%u ", key, width, height);
		}
	}

	return comand;
}

static GString *get_command(struct ffmpeg_wrap *wrap)
{
	GString *comand;

	comand = g_string_new("/bin/ffmpeg ");

	/* 输入参数，好吧，实际上并没有设置(<: */
	get_kwargs(comand, wrap->input_dict);

	g_string_append_printf(comand, "-i %s ", wrap->input_url);

	/* 输出参数 */
	get_kwargs(comand, wrap->output_dict);

	g_string_append(comand, wrap->output_url);

	/* 重名时是否覆盖输出文件 */
	if (wrap->overwrite)
		g_string_append(comand, " -y");

	return comand;
}

void ffmpeg_wrap_run(struct ffmpeg_wrap *wrap)
{
	GString *comand;

	comand = get_command(wrap);
	/* 需要增加system()或popen() */
	g_print("%s\n", comand->str);
	g_string_free(comand, TRUE);
}

int main(int argc, char **argv)
{
	struct ffmpeg_wrap *wrap;

	wrap = ffmpeg_wrap_new();
	ffmpeg_wrap_input_set_url(wrap, "input.mp4");
	ffmpeg_wrap_output_set_url(wrap, "output.mp4");
	ffmpeg_wrap_output_set_fps(wrap, 25);
	ffmpeg_wrap_output_set_vcodec(wrap, "h264");
	ffmpeg_wrap_output_set_acodec(wrap, "aac");
	ffmpeg_wrap_output_set_size(wrap, 1280, 720);
	ffmpeg_wrap_output_set_overwrite(wrap);
	ffmpeg_wrap_run(wrap);
	ffmpeg_wrap_free(wrap);

	return 0;
}
